home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / Apps / DevTools / eText5 / Source / Component.subproj / eTAudioComponent.m < prev    next >
Encoding:
Text File  |  1995-02-11  |  7.9 KB  |  251 lines

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //    FILENAME:    eTAudioComponent.h
  3. //    SUMMARY:    Implementation for a container of audio data.
  4. //    SUPERCLASS:    Object
  5. //    INTERFACE:    None, but it "exports" eTAudioComponentIcon and IconH.
  6. //    PROTOCOLS:    <ComponentData,
  7. //                ETFDSupport,HTMDSupport,LaTeXSupport>
  8. //    AUTHOR:        Rohit Khare
  9. //    COPYRIGHT:    (c) 1994 California Institure of Technology, eText Project
  10. ///////////////////////////////////////////////////////////////////////////////
  11. //    IMPLEMENTATION COMMENTS
  12. //        This is a subclass that externalizes audio components. Manages
  13. //    a Sound object. useSound:... has been included to allow passing
  14. //    in Sounds that are not on disk (as with paste:s)
  15. //        We eventually want to support WAV and AIFF types (which NX Sound
  16. //    does not. Perhaps adopt SOX code (talk to nick christopher)?
  17. ///////////////////////////////////////////////////////////////////////////////
  18. //    HISTORY
  19. //    07/14/94:    Created. Aliases the NeXTSTEP Sound API.
  20. ///////////////////////////////////////////////////////////////////////////////
  21.  
  22. #import "eTAudioComponent.h"
  23. #define    _eTAudioComponentVERSION 10
  24.  
  25. @implementation eTAudioComponent
  26. //    id theSound;
  27.  
  28. - theSound 
  29. {    if (!theSound) theSound = [[Sound alloc] init];
  30.     return theSound;
  31. }
  32. + newSoundNamed:(const char *)theName
  33. {
  34.     // This is a fake implementation. see eTImageComponent for a real one.
  35.     id newObj;
  36.     
  37.     newObj = [[eTAudioComponent alloc] initInDoc:nil linked:NO];
  38.     theSound = [Sound findSoundFor:theName];
  39.     componentName = NXUniqueString(theName);
  40.     return newObj;
  41. }
  42. - useSound:(Sound *)newSound 
  43.       name:(const char *) newComponentName
  44.       path:(const char *) newCurrentPath
  45. {
  46.     theSound = newSound;
  47.     componentName = NXUniqueString(newComponentName);
  48.     currentPath = NXUniqueString(newCurrentPath);
  49.     shouldEdit &= !isLinked;    // should we ever muck with linked snds?
  50.     return self;
  51. }
  52.  
  53. - readComponentFromPath:(NXAtom)newPath
  54. {
  55.     [super readComponentFromPath:newPath];
  56.     // attempt to load from currentPath
  57.     theSound = nil;
  58.     if (currentPath && *currentPath) {
  59.         theSound = [[Sound alloc] initFromSoundfile:currentPath];
  60.         shouldEdit &= !isLinked;    // should we ever muck with linked snds?
  61.     }
  62.     if (!theSound){
  63.         theSound = [Sound findSoundFor:"SystemBeep"];
  64.         shouldEdit = NO;
  65.     }
  66.     return self;
  67. }
  68. - writeComponentToPath:(NXAtom)path inFormat:(int) theFormat
  69. {
  70.     const char *tmp;
  71.     char target[MAXPATHLEN];
  72.     id     altSound;
  73.     
  74.     switch(theFormat) {
  75.         case ETFD_FMT:
  76.         //    if it's not (a link) or (clean and the target is found),
  77.         //        if the (source is found and it's clean), copy
  78.         //        else write.
  79.             sprintf(target,"%s/%s",path,componentName);
  80.             if (!((isLinked) || ((!isDirty) && (!access(target,F_OK|R_OK))))){
  81.                 if ((!isDirty) && *currentPath && 
  82.                     (!access(currentPath, F_OK|R_OK))) {
  83.                     // copy
  84.                     char cmd[2*MAXPATHLEN];
  85.  
  86.                     sprintf(cmd,"cp -rp \"%s\" \"%s\"", currentPath, target);
  87.                     system(cmd);
  88.                     currentPath = NXUniqueString(target);
  89.                 } else {
  90.                     if (!rindex(target, '.') || 
  91.                         strcasecmp(".snd", rindex(target, '.')))
  92.                             strcat(target, ".snd");
  93.                     [theSound writeSoundfile:target];
  94.                     currentPath = NXUniqueString(target);
  95.                     componentName = NXUniqueString(rindex(target,'/')+1);
  96.                 }
  97.                 isDirty=NO;
  98.             }
  99.             [etDoc registerComponent:componentName];
  100.             break;
  101.         
  102.         case HTMD_FMT:
  103.         case TeXD_FMT:
  104.         // Always is an .au. If it doesn't exist, copy an .au or create one.
  105.             if (componentName) tmp = componentName;
  106.             else if ([theSound name]) tmp = [theSound name];
  107.             else tmp = [[self class] name];
  108.  
  109.             sprintf(target,"%s/%s",path,tmp);
  110.             if (!rindex(target, '.') || strcasecmp(".au", rindex(target, '.')))
  111.                 strcat(target, ".au");
  112.             if (access(target,F_OK|R_OK) || isDirty) {
  113.                 // if currentPath is an .au, copy.
  114.                 if (rindex(currentPath, '.') &&
  115.                     (!strcasecmp(".au", rindex(currentPath, '.'))) &&
  116.                     (!access(currentPath,F_OK|R_OK))) {
  117.                     char cmd[2*MAXPATHLEN];
  118.  
  119.                     sprintf(cmd,"cp -rp \"%s\" \"%s\"", currentPath, target);
  120.                     system(cmd);
  121.                 } else {
  122.                     altSound = [[Sound alloc] init];
  123.                     [altSound copySound:theSound];
  124.                     [altSound convertToFormat:SND_FORMAT_MULAW_8
  125.                                  samplingRate:SND_RATE_CODEC
  126.                                  channelCount:1];                 
  127.                     [altSound writeSoundfile:target];
  128.                     altSound = [altSound free];
  129.                 }
  130.             }
  131.             [etDoc registerComponent:rindex(target,'/')+1];
  132.             break;
  133.     }
  134.     return self;
  135. }
  136. - writeComponentToPboard:thePboard
  137. {
  138.     [thePboard declareTypes:&NXSoundPboard num:1 owner:nil];
  139.     [theSound writeToPasteboard:thePboard];
  140.     // here we copy code from the superclass because of the order of
  141.     // addTypes: calls and the preference-order of Pasteboard
  142.     [thePboard     addTypes:&NXFilenamePboardType num:1 owner:nil];
  143.     [thePboard     writeType:NXFilenamePboardType 
  144.                 data:currentPath length:strlen(currentPath)];
  145.     return self;
  146. }
  147. - addToPboard:pboard
  148. {
  149.     NXStream *memstream;
  150.     
  151.     memstream = NXOpenMemory(NULL, 0, NX_READWRITE);
  152.     if (memstream) {
  153.         [theSound writeSoundToStream:memstream];
  154.         [pboard addTypes:&NXSoundPboardType num:1 owner:nil];
  155.         [pboard writeType:NXSoundPboardType fromStream:memstream];
  156.         NXCloseMemory(memstream, NX_FREEBUFFER);
  157.     }
  158.     return self;
  159. }
  160. - readComponentFromPboard:thePboard
  161. {
  162.     [super readComponentFromPboard:thePboard];
  163.     // ok, so now we have a quasi-valid entry in currentPath
  164.     // If the sound can init from thePboard, go right ahead.
  165.  
  166.     theSound = [[Sound alloc] initFromPasteboard:thePboard];
  167.     if (!theSound) {
  168.         //ok, there's no NXSoundPboardType data. Can we get a file?
  169.         if (currentPath && *currentPath) {
  170.             theSound = [[Sound alloc] initFromSoundfile:currentPath];
  171.         }
  172.         shouldEdit &= !isLinked;    // should we ever muck with linked snds?
  173.         if (!theSound){
  174.             theSound = [Sound findSoundFor:"SystemBeep"];
  175.             shouldEdit = NO;
  176.         }
  177.     }
  178.     // special case: If we paste raw audio data and there's no path,
  179.     // componentName is currently "Untitled-%d"; we need to cat ".snd"
  180.     if (!(currentPath && *currentPath)) {
  181.         char tmp[MAXPATHLEN];    // hey, it's only stack space... :)
  182.         
  183.         strcpy(tmp, componentName);
  184.         if (!rindex(tmp, '.') || strcasecmp(".snd", rindex(tmp, '.')))
  185.             strcat(tmp, ".snd");
  186.         componentName = NXUniqueString(tmp);
  187.     }
  188.  
  189.     return self;
  190. }
  191.  
  192. - readRichText:(NXStream *)stream forView:view
  193. {
  194.     [super readRichText:stream forView:view];
  195.     if (currentPath && *currentPath) {
  196.         theSound = [[Sound alloc] initFromSoundfile:currentPath];
  197.     }
  198.     shouldEdit &= !isLinked;    // should we ever muck with linked snds?
  199.     if (!theSound){
  200.         theSound = [Sound findSoundFor:"SystemBeep"];
  201.         shouldEdit = NO;
  202.     }
  203.     return self;
  204. }
  205. - writeRichText:(NXStream *)stream forView:view
  206. {
  207.     // since this method is called before any writeComponents, we attempt
  208.     // to precompute whether an extension will be added
  209.     
  210.     char target[MAXPATHLEN];
  211.     
  212.     /*if (!etDoc)*/ etDoc = [view etDoc]; // Always reset; bugfix for shared audio, 12/23
  213.     strcpy(target, componentName);
  214.     if (!rindex(target, '.') || strcasecmp(".snd", rindex(target, '.'))) {
  215.         strcat(target, ".snd");
  216.         componentName = NXUniqueString(target);
  217.     }
  218.     return [super writeRichText:stream forView:view];
  219. }
  220. - writeHTML:(NXStream *)stream forView:view
  221.     {return [self writeHTML:stream forView:view andClose:YES];}
  222. - writeHTML:(NXStream *)stream forView:view andClose:(BOOL)closeIt
  223. {
  224.     const char *tmp;
  225.  
  226.     /*if (!etDoc)*/ etDoc = [view etDoc]; // Always reset; bugfix for shared audio, 12/23
  227.     if (componentName) tmp = componentName;
  228.     else if ([theSound name]) tmp = [theSound name];
  229.     else tmp = [[self class] name];
  230.     
  231.     NXPrintf(stream, "<A HREF=\"%V%V\">",tmp,
  232.     ((!rindex(tmp, '.') || strcmp(".au", rindex(tmp, '.')))?".au":""));
  233.     if (closeIt) {
  234.         NXPrintf(stream, "%v</A>",tmp);
  235.     }
  236.     return self;
  237. }
  238.  
  239. - writeLaTeX:(NXStream *)stream forView:view
  240. {
  241.     const char *tmp;
  242.  
  243.     /*if (!etDoc)*/ etDoc = [view etDoc]; // Always reset; bugfix for shared images, 12/23
  244.     if (componentName) tmp = componentName;
  245.     else if ([theSound name]) tmp = [theSound name];
  246.     else tmp = [[self class] name];
  247.     NXPrintf(stream, "\n\\footnote{A reference to the sound %w%w}",
  248.     tmp,((!rindex(tmp, '.') || strcmp(".au", rindex(tmp, '.')))?".au":""));
  249.     return self;
  250. }
  251. @end